# -*- coding: utf-8 -*-
"""
 ----------------------------------------
|File Name:     rng
|Author:        WYT
|date:          2021/7/2
 ----------------------------------------
|  Change Activity:
|                   2021/7/2:
-----------------------------------------
"""
import datetime
import math
import random
import time

from util.encryption_password.core import CryptoJs
from util.encryption_password.prng4 import PrngNewstate


class Rng():
    state = None
    pool = None
    pptr = None
    psize = 256


# 给数组扩容
def array_capacity(list_obj, index):
    while True:
        if len(list_obj) < index + 1:
            list_obj.append(0)
        else:
            break


def rng_seed_int(x):
    array_capacity(Rng.pool, Rng.pptr)
    Rng.pool[Rng.pptr] ^= x & 255
    Rng.pptr += 1
    array_capacity(Rng.pool, Rng.pptr)
    Rng.pool[Rng.pptr] ^= (x >> 8) & 255
    Rng.pptr += 1
    array_capacity(Rng.pool, Rng.pptr)
    Rng.pool[Rng.pptr] ^= (x >> 16) & 255
    Rng.pptr += 1
    array_capacity(Rng.pool, Rng.pptr)
    Rng.pool[Rng.pptr] ^= (x >> 24) & 255
    Rng.pptr += 1
    if Rng.pptr >= Rng.psize:
        Rng.pptr -= Rng.psize


def get_seconds():
    datetime_object = datetime.datetime.now()
    now_timetuple = datetime_object.timetuple()
    now_second = time.mktime(now_timetuple)
    time_f = now_second * 1000 + datetime_object.microsecond / 1000
    return int(time_f)


def rng_seed_time():
    rng_seed_int(get_seconds())


if Rng.pool is None:
    Rng.pool = []
    Rng.pptr = 0
    t: int
    # 这一段不翻译 判断浏览器名称 和 版本
    # if (navigator.appName == "Netscape" & & navigator.appVersion < "5" & & window.crypto) {
    # // Extract entropy (256 bits) from NS4 RNG if available
    # var z = window.crypto.random(32);
    # for (t = 0; t < z.length; ++t)
    # rng_pool[rng_pptr++] = z.charCodeAt(t) & 255;
    # }
    while Rng.pptr < Rng.psize:
        t = math.floor(65536 * random.random())
        array_capacity(Rng.pool, Rng.pptr)
        Rng.pool[Rng.pptr] = CryptoJs.unsigned_right_shitf(t, 8)
        Rng.pptr += 1
        array_capacity(Rng.pool, Rng.pptr)
        Rng.pool[Rng.pptr] = t & 255
        Rng.pptr += 1

    Rng.pptr = 0
    rng_seed_time()


def rng_get_byte():
    if Rng.state is None:
        rng_seed_time()
        Rng.state = PrngNewstate()
        Rng.state.init(Rng.pool)
        Rng.pptr = 0
        while Rng.pptr < len(Rng.pool):
            Rng.pptr += 1
            array_capacity(Rng.pool, Rng.pptr)
            Rng.pool[Rng.pptr] = 0
        Rng.pptr = 0
    return Rng.state.next()


class SecureRandom(object):

    @classmethod
    def rng_get_bytes(cls, ba):
        for i in range(0, len(ba)):
            ba[i] = rng_get_byte()


if __name__ == '__main__':
    get_seconds()
